<template>
  <div class="goods-sku">
    <dl v-for="itemList in goods.specs" :key="itemList.id">
      <dt>{{ itemList.name }}</dt>
      <dd>
        <template v-for="item in itemList.values" :key="item.name">
          <img v-if="item.picture" :class="{selected: item.selected, disabled:item.disabled}" :src="item.picture" alt="" :title="item.name" @click="clickSpecs(itemList, item)">
          <span v-else :class="{selected: item.selected, disabled:item.disabled}" @click="clickSpecs(itemList, item)">{{ item.name }}</span>
        </template>
      </dd>
    </dl>
  </div>
</template>

<script>
import getPowerSet from '@/vender/pover-set'
const spliter = '★'

// 首先要获取sku库存情况,在页面渲染库存数据
// 1.得到一个字典对象
const getPathMap = (skus) => {
  // 1.得到所有集合的sku，props.goods.skus
  // 2.从所有的sku中筛选出有效的sku
  // 3.根据有效的sku使用power-set算法得到一个自己
  // 4.根据子集往路径字典中存储key-value

  // 存放集合的地方
  const pathMap = {}

  skus.forEach(sku => {
    // 判断是否有库存
    if (sku.inventory > 0) {
      // 1.计算当前库存的sku子集
      // 2.例如：[1,2,3] = [[1],[2],[3],[1,2],[1,3],[2,3],[1,2,3]]
      // 可选值数组
      const ArrValue = sku.specs.map(val => val.valueName)
      // 创建子集路径
      const ArrValuePowerSet = getPowerSet(ArrValue)

      // 遍历子集，往pathMap插入数据
      ArrValuePowerSet.forEach(arr => {
        // 根据arr得到字符串的key 约定key的格式['蓝色','美国'] => '蓝色★美国'
        const key = arr.join(spliter)

        // 给pathMap设置数据
        if (pathMap[key]) {
          console.log(pathMap[key])
          pathMap[key].push(sku.id)
        } else {
          pathMap[key] = [sku.id]
        }
      })
    }
  })
  return pathMap
}
// 定义默认选中方法
const initDefaultSelected = (goods, skuId) => {
  // 找出sku的信息
  // 遍历每一个按钮,按钮的数值等于sku记录的数值,则默认选中

  const sku = goods.skus.find(item => item.id === skuId)
  goods.specs.forEach((item, i) => {
    const val = item.values.find(valItem => valItem.name === sku.specs[i].valueName)
    val.selected = true
  })
}

// 得到当前选中的规格值的数组
const getSelectedValues = (specs) => {
  const arr = []
  console.log(specs)
  specs.forEach(item => {
    // 选中的按钮对象
    // 返回每一个规格属性中的selected值
    const selectedVal = item.values.find(val => val.selected)

    arr.push(selectedVal ? selectedVal.name : undefined)
  })
  return arr
}

// 更新按钮禁用状态
const updateDisabledStatus = (specs, pathMap) => {
  console.log(specs)
  // 1.约定每一个按钮的状态都由本身的disabled数据来进行控制
  specs.forEach((item, i) => {
    const selectedValue = getSelectedValues(specs)

    item.values.forEach(val => {
    // 2. 判断当前是否选中，是选中的话不用进行判断
      if (val.selected) return
      // 3. 那当前的值按照顺序套入选中值的数组中
      selectedValue[i] = val.name
      // 4. 提出undefined的数值，按照分隔符拼接key 将两个规格已点击的数值数组合并起来 undefined不能合并
      const key = selectedValue.filter(value => value).join(spliter)
      // 如果合并不成功的 则为undefined 为false  取反则为true ,给DOM元素disabled类名添加true 则启动禁用状态
      // 拿着key去路径字典中查找是否有数据，有可以点击，没有就禁用（true）
      val.disabled = !pathMap[key]
    })
  })
}
export default {
  name: 'GoodsSku',
  props: {
    // 接受商品详细信息
    goods: {
      type: Object,
      default: () => ({})
    },
    skuId: {
      type: String,
      default: ''
    }
  },
  setup (props, { emit }) {
    const pathMap = getPathMap(props.goods.skus)
    if (props.skuId) {
      // 根据skuId初始化选中
      initDefaultSelected(props.goods, props.skuId)
    }

    // 组件初始化的时候更新禁用状态
    updateDisabledStatus(props.goods.specs, pathMap)

    // 1.选中与取消选中,约定去每一个按钮都拥有自己的选中状态数据:selected
    // 1.1 点击的是已经选中的,只需要取消当前的选中即可
    // 1.2 点击的是未选中的,把同一个规格的按钮改成为选中的状态,当前点击的改成选中
    const clickSpecs = (item, val) => {
      console.log(item, val)
      // 选中与取消选中的逻辑
      if (val.disabled) return
      // 如果不是禁用正常运行
      if (val.selected) {
        val.selected = false
      } else {
        // 当点击时,除了点击目标外 其他数据的selected都为false
        item.values.forEach(itemVal => {
          itemVal.selected = false
        })
        // 点击目标边框高亮
        val.selected = true
      }
      // 点击按钮的时候,更新按钮禁用的状态
      updateDisabledStatus(props.goods.specs, pathMap)
      // 将你选择的sku信息通知父组件(skuId,price,oldPrice,inventory,specsText)
      // 1. 选择完整的sku组合按钮,才可以拿到这些信息,通知父组件
      // 2. 不是完整的sku组合按钮,提交空对象父组件
      const validSelectedValues = getSelectedValues(props.goods.specs).filter(v => v)
      console.log(validSelectedValues)
      if (validSelectedValues.length === props.goods.specs.length) {
        // 完整
        const skuId = pathMap[validSelectedValues.join(spliter)]
        const sku = props.goods.skus.find(sku => sku.id === skuId[0])
        emit('change', {
          skuId: sku.id, // 库存id
          price: sku.price, // 商品价格
          oldPrice: sku.oldPrice, // 商品原价
          inventory: sku.inventory, // 商品库存
          // 属性集合名: 属性值 属性名1: 属性值1 ....这样的字符串
          specsText: sku.specs.reduce((p, c) => `${p} ${c.name}: ${c.valueName}`, '').trim()

        })
      } else {
        emit('change', {})
      }
    }

    return { clickSpecs }
  }
}
</script>

<style lang="less" scoped>
.sku-state-mixin () {
  border: 1px solid #e4e4e4;
  margin-left: 10px;
  cursor: pointer;
  &.selected {
    border-color: @xtxColor;
  }
  &.disabled {
    opacity: 0.6;
    border-style: dashed;
    cursor: not-allowed;
  }
}
.goods-sku {
 padding-left: 10px;
 padding-top: 20px;
 dl {
  display: flex;
  padding-bottom: 10px;
  align-items: center;
  dt {
    width: 50px;
    color: #999;
  }
  dd {
    width: 400px;
    display: flex;
    flex-wrap: wrap;
    color: #666;
    line-height: 40px;
    overflow-y: scroll;
    >img {
      width: 50px;
      height: 50px;
      .sku-state-mixin()
    }
    >span {
      display: inline-block;
      height: 30px;
      line-height: 28px;
      padding: 0 20px;
      .sku-state-mixin()
    }
  }
 }
}
</style>
